package maple.util;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import plplan.javaapi.EnumAlgorithm;
import plplan.javaapi.PLPlan;
import plplan.javaapi.PlPlanException;

import maple.lang.Language;
import maple.util.tasks.GatewayTask;
import maple.util.tasks.MasterTask;

public class Planner extends Object
{
	public static enum Property{ OPERATOR, PRECONDITION, POSTCONDITION };

	/**
	 * return the adjusted string with the specified interval and receiver 
	 *
	 * @param	plan		the specified plan
	 * @param	interval	the specified interval
	 * @param	receiver	the specified receiver
	 * @return	the adjusted string with the specified interval and receiver 
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	private static String adjust( final String plan, final String interval, final String receiver )
	{
		String adjusted_plan = plan;

		String[] tokens = plan.split( Language.DELIMITER );
		switch( Language.Instruction.valueOf( tokens[ 1 ] ) )
		{
			case READ: case WRITE:
				adjusted_plan = adjusted_plan 
							    + Language.DELIMITER
					            + GatewayTask.Property.INTERVAL.toString()
								+ Language.ASSIGN
								+ Language.QUOTE
								+ interval
								+ Language.QUOTE
								+ Language.DELIMITER
								+ GatewayTask.Property.RECEIVER.toString()
								+ Language.ASSIGN
								+ Language.QUOTE
								+ receiver
								+ Language.QUOTE;
				break;
			case INTERPRET:
				break;
			case SUBSCRIBE:
				break;
		}

		return adjusted_plan;
	}
	
	/**
	 * return the list of operators to achieve the specified goal with the specified facts, operators, interval and receiver or null if the goal can not achieve
	 *
	 * @param	fact		the specified fact
	 * @param	operators	the specified operators
	 * @param	goal		the specified goal
	 * @param	interval	the specified interval
	 * @param	receiver	the specified receiver
	 * @return	the list of operators to achieve the specified goal with the specified facts, operators, interval and receiver
	 *
	 * @author	snowfoxy
	 * @since	2011-11-15
	 */
	public static Vector< String > plan( final String fact, final Vector< String > operators, final String goal, final String interval, final String receiver )
	{
		try
		{
			// set the initial condition
			PLPlan planner = new PLPlan();
			planner.setAlgorithm( EnumAlgorithm.GRAPHPLAN );
			planner.addFact( fact );
			planner.addGoalFact( goal );

			// add operators
			for( String operator : operators )
			{
				String[] tokens = operator.split( Language.TAB );

				List< String > preconditions = new ArrayList< String >();
				String[] items = tokens[ 1 ].split( Language.COMMA );
				for( String item : items )
				{
					preconditions.add( item );
				}
				List< String > postconditions = new ArrayList< String >();
				items = tokens[ 2 ].split( Language.COMMA );
				for( String item : items )
				{
					postconditions.add( item );
				}
				planner.addOperator( tokens[ 0 ], 
						preconditions,
						new ArrayList< String >(),
						postconditions );
			}

			// find the plan
			Vector< String > commands = new Vector< String >();
			List plans = planner.findPlan();
			for( Object object : plans )
			{
				String plan = object.toString();
				plan = plan.substring( 1, plan.length() - 1 );
				String[] steps = plan.split( ", " );
				for( String step : steps )
				{
					commands.add( adjust( step, interval, receiver ) );
				}
			}
			return commands;
		}
		catch( PlPlanException e )
		{
		}
		catch( NullPointerException e )
		{
		}
		return null;
	}
}
